package com.ruoyi.assemble.common.utils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 幂函数
 * @author ZWQ
 */
public class PowFunction {
    private static final String POINT_DIGIT = "#.0000";
    /**
     * 拟合幂函数
     * @author ZWQ
     */
    public Map<String,Double> powFunction(List<List<Double>> data){
        Map<String,Double> result = new HashMap<>();
        Double xSum = 0.00;
        Double ySum = 0.00;
        Double xySum = 0.00;
        Double x2Sum = 0.00;
        Double a = 0.00;
        Double b = 0.00;
        DecimalFormat df = new DecimalFormat(POINT_DIGIT);
        int n = data.size();
        for(int i =0;i<n;i++){
            if(data.get(i).get(0) != 0.0 || data.get(i).get(1) != 0.0){
                if(data.get(i).get(0) == 0.0){
                    ySum = ySum + Math.log(data.get(i).get(1));
                    continue;
                }
                if(data.get(i).get(1) == 0.0){
                    xSum = xSum + Math.log(data.get(i).get(0));
                    continue;
                }
                xSum = xSum + Math.log(data.get(i).get(0));
                ySum = ySum + Math.log(data.get(i).get(1));
                x2Sum = x2Sum + Math.log(data.get(i).get(0))*Math.log(data.get(i).get(0));
                xySum = xySum + Math.log(data.get(i).get(0)) * Math.log(data.get(i).get(1));
            }
        }
        //被除数不能为0
        if(x2Sum - xSum*xSum == 0 ){
            a = 0.0;
            b = 0.0;
        }else{
            b = (xySum - ySum*xSum/n) / (x2Sum - xSum*xSum/n);
            a = Math.exp((ySum - b*xSum)/n);
        }

        result.put("a",Double.parseDouble(df.format(a)));
        result.put("b",Double.parseDouble(df.format(b)));
        return result;
    }
    /**
     * 获取预测结果
     * @author ZWQ
     */
    public List<List<Double>> getPowData(Double a,Double b ,List<List<Double>> realData){
        List<List<Double>> predictData = new ArrayList<>(realData.size());
        DecimalFormat df = new DecimalFormat(POINT_DIGIT);
        for(List<Double> data:realData){
            List<Double> result = new ArrayList<>(2);
            if(data.get(0) == 0.0 && data.get(1) == 0.0){
                continue;
            }
            result.add(data.get(0));
            if(data.get(0) == 0.0){
                result.add(0.0);
            }else{
                Double y = Double.parseDouble(df.format(a*Math.pow(data.get(0),b)));
                result.add(y);
            }
            predictData.add(result);
        }
        return predictData;
    }
}
